package com.chenfan.mcn.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.chenfan.mcn.clients.baseinfo.BaseInfoClient;
import com.chenfan.mcn.clients.baseinfo.BaseInfoDataMoveDTO;
import com.chenfan.mcn.clients.baseinfo.BaseInfoDataMoveVO;
import com.chenfan.mcn.extension.log.FieldChangeOperateLog;
import com.chenfan.mcn.clients.finance.FinanceClient;
import com.chenfan.mcn.clients.finance.FinanceDataMoveDto;
import com.chenfan.mcn.clients.finance.FinanceDataMoveVo;
import com.chenfan.mcn.clients.privilege.PrivilegeClient;
import com.chenfan.mcn.clients.privilege.SUser;
import com.chenfan.mcn.clients.privilege.SUserVo;
import com.chenfan.mcn.config.UserVoContextHolder;
import com.chenfan.mcn.constant.NumberCst;
import com.chenfan.mcn.dao.*;
import com.chenfan.mcn.enums.BusinessTypeEnum;
import com.chenfan.mcn.enums.LogBusinessTypeEnum;
import com.chenfan.mcn.extension.log.OperationTypeEnum;
import com.chenfan.mcn.exception.McnErrorCode;
import com.chenfan.mcn.exception.RpcResultException;
import com.chenfan.common.extension.spring.TransactionUtils;
import com.chenfan.mcn.component.OperateLogHandler;
import com.chenfan.mcn.model.*;
import com.chenfan.mcn.model.dto.BusinessDataMoveLogQueryDTO;
import com.chenfan.mcn.service.BusinessDataMoveService;
import com.chenfan.mcn.utils.BusinessAssert;
import com.chenfan.mcn.utils.NoRepeatableArrayList;
import lombok.Builder;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 业务数据转移服务接口实现类
 *
 * @author wulg
 * @date 2021-10-22
 **/
@Slf4j
@Service
public class BusinessDataMoveServiceImpl implements BusinessDataMoveService {

    @Autowired
    private BusinessDataMoveLogMapper businessDataMoveLogMapper;

    @Autowired
    private StarBasicDataMapper starBasicDataMapper;

    @Autowired
    private DiscountApprovalMapper discountApprovalMapper;

    @Autowired
    private YearFrameContractMapper yearFrameContractMapper;

    @Autowired
    private IncomeContractMapper incomeContractMapper;

    @Autowired
    private PurchaseContractMapper purchaseContractMapper;

    @Autowired
    private ContractExcutionOrderMapper contractExcutionOrderMapper;

    @Autowired
    private AnnualRebateApprovalMapper annualRebateApprovalMapper;

    @Autowired
    private StarRebateContractMapper starRebateContractMapper;

    @Autowired
    private PrivilegeClient privilegeClient;

    @Autowired
    private FinanceClient financeClient;

    @Autowired
    private BaseInfoClient baseInfoClient;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean execute(BusinessDataMoveLog bdmLog) {
        List<Integer> businessTypeList = JSONObject.parseObject(bdmLog.getBusinessType(), new TypeReference<List<Integer>>(){});
        BusinessAssert.notEmpty(businessTypeList, McnErrorCode.PARAM_ERROR, "[多选]业务类型-不能为空");
        BusinessAssert.isTrue(!BusinessTypeEnum.existIllegalType(businessTypeList), McnErrorCode.PARAM_ERROR, "[多选]业务类型-存在非法标记");
        //查询用户
        List<SUser> userList = privilegeClient.getUserByIds(Arrays.asList(bdmLog.getSourceUserId(), bdmLog.getTargetUserId())).getObj();
        BusinessAssert.notEmpty(userList, McnErrorCode.DATA_NOT_FOUND, "查询不到源&目标用户信息");
        Map<Long,SUser> userMap = userList.stream().collect(Collectors.toMap(SUser::getUserId, sUser -> sUser));
        BusinessAssert.isTrue(userMap.containsKey(bdmLog.getSourceUserId()), McnErrorCode.DATA_NOT_FOUND, "查询不到源用户信息");
        BusinessAssert.isTrue(userMap.containsKey(bdmLog.getTargetUserId()), McnErrorCode.DATA_NOT_FOUND, "查询不到目标用户信息");
        //查询部门
        List<SUserVo> departmentList = privilegeClient.getDepartmentByUserIds(Arrays.asList(bdmLog.getSourceUserId(), bdmLog.getTargetUserId())).getObj();
        BusinessAssert.notEmpty(departmentList, McnErrorCode.DATA_NOT_FOUND, "查询不到源&目标用户-部门信息");
        Map<Long,SUserVo> departmentMap = departmentList.stream().collect(Collectors.toMap(SUserVo::getUserId, sUserVo -> sUserVo));
        BusinessAssert.isTrue(departmentMap.containsKey(bdmLog.getSourceUserId()), McnErrorCode.DATA_NOT_FOUND, "查询不到源用户-部门信息");
        BusinessAssert.isTrue(departmentMap.containsKey(bdmLog.getTargetUserId()), McnErrorCode.DATA_NOT_FOUND, "查询不到目标用户-部门信息");

        SUser sourceUser = userMap.get(bdmLog.getSourceUserId());
        bdmLog.setSourceUserName(sourceUser.getUsername());
        if(departmentMap.containsKey(bdmLog.getSourceUserId())) {
            bdmLog.setSourceDepartmentId(departmentMap.get(bdmLog.getSourceUserId()).getDepartmentId());
        }
        bdmLog.setSourceCompanyId(sourceUser.getCompanyId());

        SUser targetUser = userMap.get(bdmLog.getTargetUserId());
        bdmLog.setTargetUserName(targetUser.getUsername());
        if(departmentMap.containsKey(bdmLog.getTargetUserId())) {
            bdmLog.setTargetDepartmentId(departmentMap.get(bdmLog.getTargetUserId()).getDepartmentId());
            bdmLog.setTargetDepartmentName(departmentMap.get(bdmLog.getTargetUserId()).getDepartmentName());
        }
        bdmLog.setTargetCompanyId(targetUser.getCompanyId());
        bdmLog.setCount(0L);
        List<DataMoveResultDetail> detailList = new ArrayList<>();
        TransactionUtils.afterRollback(() -> {
            //针对异常类型
            bdmLog.setCount(0L);
            bdmLog.setStatus(NumberCst.TWO);
            bdmLog.setResult(null);
            bdmLog.setEndTime(new Date());
            businessDataMoveLogMapper.insert(bdmLog);
        });
        //mcn-业务数据转移
        this.moveBusinessDataOfMcn(bdmLog, businessTypeList, detailList);
        //财务-业务数据转移
        FinanceDataMoveVo financeDataMoveVo = this.moveBusinessDataOfFinance(bdmLog, businessTypeList, detailList);
        //baseInfo-业务数据转移
        this.moveBusinessDataOfBaseInfo(bdmLog, businessTypeList, detailList, financeDataMoveVo);
        bdmLog.setResult(JSONObject.toJSONString(detailList));
        bdmLog.setEndTime(new Date());
        bdmLog.setStatus(NumberCst.ONE);
        try {
            boolean result = businessDataMoveLogMapper.insert(bdmLog) > 0;
            if(result) {
                //记录操作日志
                this.insertOperateLogs(bdmLog, detailList);
            }
            return result;
        } catch (Exception e) {
            //回滚
            if(CollectionUtils.isNotEmpty(detailList)) {
                List<Integer> tempList = detailList.stream().map(DataMoveResultDetail::getBusinessType).distinct().collect(Collectors.toList());
                if(CollectionUtils.isNotEmpty(BusinessTypeEnum.filterFinance(tempList))) {
                    this.rollbackFinance(bdmLog.getTaskCode());
                }
                if(CollectionUtils.isNotEmpty(BusinessTypeEnum.filterBaseInfo(tempList))) {
                    this.rollbackBaseInfo(bdmLog.getTaskCode());
                }
            }
            throw e;
        }
    }

    @Override
    public Page<BusinessDataMoveLog> queryLogs(BusinessDataMoveLogQueryDTO queryDto) {
        Page<BusinessDataMoveLog> result = businessDataMoveLogMapper.selectPage(new Page<>(queryDto.getPageNum(), queryDto.getPageSize()),
                Wrappers.lambdaQuery(BusinessDataMoveLog.class)
                .eq(queryDto.getStatus() != null, BusinessDataMoveLog::getStatus, queryDto.getStatus())
                .eq(queryDto.getOperatorId() != null, BusinessDataMoveLog::getOperatorId, queryDto.getOperatorId())
                .like(StringUtils.isNotBlank(queryDto.getOperatorName()), BusinessDataMoveLog::getOperatorName, queryDto.getOperatorName())
                .ge(queryDto.getStartTime() != null, BusinessDataMoveLog::getStartTime, queryDto.getStartTime())
                .le(queryDto.getEndTime() != null, BusinessDataMoveLog::getStartTime, queryDto.getEndTime())
                        .eq(BusinessDataMoveLog::getTenantId,UserVoContextHolder.getTenantId())
                .orderByDesc(BusinessDataMoveLog::getStartTime));
        return result;
    }

    /**
     * 转移业务数据-财务
     * @param bdmLog
     * @param businessTypeList
     * @return
     */
    private FinanceDataMoveVo moveBusinessDataOfFinance(BusinessDataMoveLog bdmLog, List<Integer> businessTypeList, List<DataMoveResultDetail> result) {
        List<Integer> financeBusinessTypeList = BusinessTypeEnum.filterFinance(businessTypeList);
        if(CollectionUtils.isEmpty(financeBusinessTypeList)) {
            return null;
        }
        //转移财务的所有人数据
        FinanceDataMoveDto commitRequest = new FinanceDataMoveDto();
        commitRequest.setTaskCode(bdmLog.getTaskCode());
        commitRequest.setBusinessTypeList(financeBusinessTypeList);
        commitRequest.setSourceUserId(bdmLog.getSourceUserId());
        commitRequest.setTargetUserId(bdmLog.getTargetUserId());
        commitRequest.setOperatorId(bdmLog.getOperatorId());
        commitRequest.setOperatorName(bdmLog.getOperatorName());
        commitRequest.setTanantId(bdmLog.getTenantId());
        FinanceDataMoveVo financeDataMoveVo= null;
        try {
            financeDataMoveVo = financeClient.dataMove(commitRequest).getObj();
            if(financeDataMoveVo == null || CollectionUtils.isEmpty(financeDataMoveVo.getItems())) {
                return null;
            }
            financeDataMoveVo.getItems().forEach(item -> {
                result.add(DataMoveResultDetail.builder().businessType(item.getBusinessType()).ids(item.getIds()).build());
                if(CollectionUtils.isNotEmpty(item.getIds())) {
                    bdmLog.setCount(ObjectUtils.defaultIfNull(bdmLog.getCount(), 0L).longValue() + item.getIds().size());
                }
            });
            return financeDataMoveVo;
        } catch (Exception e) {
            if(rollbackIfNecessary(e)) {
                log.error("财务-业务数据转移异常！", e);
                this.rollbackFinance(bdmLog.getTaskCode());
            }
            throw e;
        }
    }
    /**
     * 转移业务数据-BaseInfo
     * @param bdmLog
     * @param businessTypeList
     * @return
     */
    private void moveBusinessDataOfBaseInfo(BusinessDataMoveLog bdmLog, List<Integer> businessTypeList, List<DataMoveResultDetail> result, FinanceDataMoveVo financeDataMoveVo) {
        List<Integer> baseInfoBusinessTypeList = BusinessTypeEnum.filterBaseInfo(businessTypeList);
        if(CollectionUtils.isEmpty(baseInfoBusinessTypeList)) {
            return;
        }
        //转移财务的所有人数据
        BaseInfoDataMoveDTO commitRequest = new BaseInfoDataMoveDTO();
        commitRequest.setTaskCode(bdmLog.getTaskCode());
        commitRequest.setBusinessTypeList(baseInfoBusinessTypeList);
        commitRequest.setSourceUserId(bdmLog.getSourceUserId());
        commitRequest.setTargetUserId(bdmLog.getTargetUserId());
        commitRequest.setStartDate(bdmLog.getStartTime());
        commitRequest.setOperatorId(bdmLog.getOperatorId());
        commitRequest.setOperatorName(bdmLog.getOperatorName());
        commitRequest.setTanantId(bdmLog.getTenantId());
        BaseInfoDataMoveVO baseInfoDataMoveVO= null;
        try {
            baseInfoDataMoveVO = baseInfoClient.userDataTransfer(commitRequest).getObj();
            if(baseInfoDataMoveVO == null || CollectionUtils.isEmpty(baseInfoDataMoveVO.getItems())) {
                return;
            }
            baseInfoDataMoveVO.getItems().forEach(item -> {
                result.add(DataMoveResultDetail.builder().businessType(item.getBusinessType()).ids(item.getIds()).build());
                if(CollectionUtils.isNotEmpty(item.getIds())) {
                    bdmLog.setCount(ObjectUtils.defaultIfNull(bdmLog.getCount(), 0L).longValue() + item.getIds().size());
                }
            });
        } catch (Exception e) {
            if(rollbackIfNecessary(e)) {
                log.error("baseInfo-业务数据转移异常！", e);
                this.rollbackBaseInfo(bdmLog.getTaskCode());
            }
            if(Objects.nonNull(financeDataMoveVo) && CollectionUtils.isNotEmpty(financeDataMoveVo.getItems())) {
                this.rollbackFinance(bdmLog.getTaskCode());
            }
            throw e;
        }
    }

    /**
     * 转移业务数据-MCN
     * @param bdmLog
     * @param businessTypeList
     */
    private void moveBusinessDataOfMcn(BusinessDataMoveLog bdmLog, List<Integer> businessTypeList, List<DataMoveResultDetail> result) {
        //红人-经纪人ID
        if(businessTypeList.contains(BusinessTypeEnum.STAR_AGENT.getType())) {
            moveStarBasicDataOfAgent(bdmLog, result);
        }
        //红人-经纪人ID
        if(businessTypeList.contains(BusinessTypeEnum.STAR_EXECUTOR.getType())) {
            moveStarBasicDataOfExecutor(bdmLog, result);
        }
        //折扣审批单
        if(businessTypeList.contains(BusinessTypeEnum.DISCOUNT_APPROVAL.getType())) {
            moveDiscountApproval(bdmLog, result);
        }
        //年框合同
        if(businessTypeList.contains(BusinessTypeEnum.YEAR_FRAME_CONTRACT.getType())) {
            moveYearFrameContract(bdmLog, result);
        }
        //收入合同
        if(businessTypeList.contains(BusinessTypeEnum.INCOME_CONTRACT.getType())) {
            moveIncomeContract(bdmLog, result);
        }
        //执行单
        if(businessTypeList.contains(BusinessTypeEnum.EXCUTION_ORDER.getType())) {
            moveExcutionOrder(bdmLog, result);
        }
        //采购合同
        if(businessTypeList.contains(BusinessTypeEnum.PURCHASE_CONTRACT.getType())) {
            movePurchaseContract(bdmLog, result);
        }
        //客户返点审批单
        if(businessTypeList.contains(BusinessTypeEnum.ANNUAL_REBATE.getType())) {
            moveAnnualRebateApproval(bdmLog, result);
        }
        //红人返点合同
        if(businessTypeList.contains(BusinessTypeEnum.STAR_REBATE_CONTRACT.getType())) {
            moveStarRebateContract(bdmLog, result);
        }
    }

    /**
     * 转移红人返点合同-业务数据
     * @param bdmLog
     * @param result
     */
    private void moveStarRebateContract(BusinessDataMoveLog bdmLog, List<DataMoveResultDetail> result) {
        List<StarRebateContract> dataList = starRebateContractMapper.selectList(Wrappers.lambdaQuery(StarRebateContract.class)
                .select(StarRebateContract::getId).eq(StarRebateContract::getOwnerId, bdmLog.getSourceUserId()));
        List<Long> ids = null;
        if(CollectionUtils.isNotEmpty(dataList)) {
            ids = dataList.stream().map(StarRebateContract::getId).collect(Collectors.toList());
            starRebateContractMapper.updateByNoStrategy(Wrappers.<StarRebateContract>lambdaUpdate()
                    .set(StarRebateContract::getOwnerId, bdmLog.getTargetUserId())
                    .set(StarRebateContract::getOwnerName, bdmLog.getTargetUserName())
                    .set(StarRebateContract::getDepartmentId, bdmLog.getTargetDepartmentId())
                    .set(StarRebateContract::getCompanyId, bdmLog.getTargetCompanyId())
                    .set(StarRebateContract::getUpdateBy, bdmLog.getOperatorId())
                    .set(StarRebateContract::getUpdateName, bdmLog.getOperatorName())
                    .set(StarRebateContract::getUpdateDate, bdmLog.getStartTime())
                    .eq(StarRebateContract::getOwnerId, bdmLog.getSourceUserId()));
            bdmLog.setCount(ObjectUtils.defaultIfNull(bdmLog.getCount(), 0L).longValue() + dataList.size());
        }
        result.add(DataMoveResultDetail.builder().businessType(BusinessTypeEnum.STAR_REBATE_CONTRACT.getType()).ids(ids).build());
    }


    /**
     * 转移红人信息-业务数据
     * @param bdmLog
     * @param result
     */
    private void moveStarBasicDataOfAgent(BusinessDataMoveLog bdmLog, List<DataMoveResultDetail> result) {
        List<StarBasicData> dataList = starBasicDataMapper.selectList(Wrappers.lambdaQuery(StarBasicData.class)
                .select(StarBasicData::getId).eq(StarBasicData::getStarAgentId, bdmLog.getSourceUserId()));
        List<Long> ids = null;
        if(CollectionUtils.isNotEmpty(dataList)) {
            ids = dataList.stream().map(StarBasicData::getId).collect(Collectors.toList());
            starBasicDataMapper.updateByNoStrategy(Wrappers.<StarBasicData>lambdaUpdate()
                    .set(StarBasicData::getStarAgentId, bdmLog.getTargetUserId())
                    .set(StarBasicData::getStarAgentName, bdmLog.getTargetUserName())
                    .set(StarBasicData::getDepartmentId, bdmLog.getTargetDepartmentId())
                    .set(StarBasicData::getCompanyId, bdmLog.getTargetCompanyId())
                    .set(StarBasicData::getUpdateBy, bdmLog.getOperatorId())
                    .set(StarBasicData::getUpdateName, bdmLog.getOperatorName())
                    .set(StarBasicData::getUpdateDate, bdmLog.getStartTime())
                    .eq(StarBasicData::getStarAgentId, bdmLog.getSourceUserId()));
            bdmLog.setCount(ObjectUtils.defaultIfNull(bdmLog.getCount(), 0L).longValue() + dataList.size());
        }
        result.add(DataMoveResultDetail.builder().businessType(BusinessTypeEnum.STAR_AGENT.getType()).ids(ids).build());
    }

    /**
     * 转移红人信息-业务数据
     * @param bdmLog
     * @param result
     */
    private void moveStarBasicDataOfExecutor(BusinessDataMoveLog bdmLog, List<DataMoveResultDetail> result) {
        List<StarBasicData> dataList = starBasicDataMapper.selectList(Wrappers.lambdaQuery(StarBasicData.class)
                .select(StarBasicData::getId).eq(StarBasicData::getExecutorId, bdmLog.getSourceUserId()));
        List<Long> ids = null;
        if(CollectionUtils.isNotEmpty(dataList)) {
            ids = dataList.stream().map(StarBasicData::getId).collect(Collectors.toList());
            starBasicDataMapper.updateByNoStrategy(Wrappers.<StarBasicData>lambdaUpdate()
                    .set(StarBasicData::getExecutorId, bdmLog.getTargetUserId())
                    .set(StarBasicData::getExecutorName, bdmLog.getTargetUserName())
                    .set(StarBasicData::getUpdateBy, bdmLog.getOperatorId())
                    .set(StarBasicData::getUpdateName, bdmLog.getOperatorName())
                    .set(StarBasicData::getUpdateDate, bdmLog.getStartTime())
                    .eq(StarBasicData::getExecutorId, bdmLog.getSourceUserId()));
            bdmLog.setCount(ObjectUtils.defaultIfNull(bdmLog.getCount(), 0L).longValue() + dataList.size());
        }
        result.add(DataMoveResultDetail.builder().businessType(BusinessTypeEnum.STAR_EXECUTOR.getType()).ids(ids).build());
    }


    /**
     * 转移执行单-业务数据
     * @param bdmLog
     * @param result
     */
    private void moveExcutionOrder(BusinessDataMoveLog bdmLog, List<DataMoveResultDetail> result) {
        //执行单-执行人ID或统筹人ID
        List<ContractExcutionOrder> dataList = contractExcutionOrderMapper.selectList(Wrappers.lambdaQuery(ContractExcutionOrder.class)
                .select(ContractExcutionOrder::getId, ContractExcutionOrder::getExcutorId, ContractExcutionOrder::getCoordinatorId)
                .eq(ContractExcutionOrder::getExcutorId, bdmLog.getSourceUserId())
                .or().eq(ContractExcutionOrder::getCoordinatorId, bdmLog.getSourceUserId()));
        List<Long> ids = null;
        if(CollectionUtils.isNotEmpty(dataList)) {
            ids = new NoRepeatableArrayList<>(dataList.size());
            List<Long> idsOfExcutor = dataList.stream().filter(e -> bdmLog.getSourceUserId().equals(e.getExcutorId()))
                    .map(ContractExcutionOrder::getId).collect(Collectors.toList());
            if(CollectionUtils.isNotEmpty(idsOfExcutor))  {
                contractExcutionOrderMapper.updateByNoStrategy(Wrappers.<ContractExcutionOrder>lambdaUpdate()
                        .set(ContractExcutionOrder::getExcutorId, bdmLog.getTargetUserId())
                        .set(ContractExcutionOrder::getExcutorName, bdmLog.getTargetUserName())
                        .set(ContractExcutionOrder::getExcutorDepartmentId, bdmLog.getTargetDepartmentId())
                        .set(ContractExcutionOrder::getExcutorDepartmentName, bdmLog.getTargetDepartmentName())
                        .set(ContractExcutionOrder::getUpdateBy, bdmLog.getOperatorId())
                        .set(ContractExcutionOrder::getUpdateName, bdmLog.getOperatorName())
                        .set(ContractExcutionOrder::getUpdateDate, bdmLog.getStartTime())
                        .eq(ContractExcutionOrder::getExcutorId, bdmLog.getSourceUserId()));
                ids.addAll(idsOfExcutor);
            }
            List<Long> idsOfCoordinator = dataList.stream().filter(e -> bdmLog.getSourceUserId().equals(e.getCoordinatorId()))
                    .map(ContractExcutionOrder::getId).collect(Collectors.toList());
            if(CollectionUtils.isNotEmpty(idsOfCoordinator))  {
                //统筹人部门ID
                contractExcutionOrderMapper.updateByNoStrategy(Wrappers.<ContractExcutionOrder>lambdaUpdate()
                        .set(ContractExcutionOrder::getCoordinatorId, bdmLog.getTargetUserId())
                        .set(ContractExcutionOrder::getCoordinatorName, bdmLog.getTargetUserName())
                        .set(ContractExcutionOrder::getUpdateBy, bdmLog.getOperatorId())
                        .set(ContractExcutionOrder::getUpdateName, bdmLog.getOperatorName())
                        .set(ContractExcutionOrder::getUpdateDate, bdmLog.getStartTime())
                        .eq(ContractExcutionOrder::getCoordinatorId, bdmLog.getSourceUserId()));
                ids.addAll(idsOfCoordinator);
            }
            bdmLog.setCount(ObjectUtils.defaultIfNull(bdmLog.getCount(), 0L).longValue() + dataList.size());
        }
        result.add(DataMoveResultDetail.builder().businessType(BusinessTypeEnum.EXCUTION_ORDER.getType()).ids(ids).build());
    }


    /**
     * 转移客户返点-业务数据
     * @param bdmLog
     * @param result
     */
    private void moveAnnualRebateApproval(BusinessDataMoveLog bdmLog, List<DataMoveResultDetail> result) {
        List<AnnualRebateApproval> dataList = annualRebateApprovalMapper.selectList(Wrappers.lambdaQuery(AnnualRebateApproval.class)
                .select(AnnualRebateApproval::getId).eq(AnnualRebateApproval::getOwnerId, bdmLog.getSourceUserId()));
        List<Long> ids = null;
        if(CollectionUtils.isNotEmpty(dataList)) {
            ids = dataList.stream().map(AnnualRebateApproval::getId).collect(Collectors.toList());
            annualRebateApprovalMapper.updateByNoStrategy(Wrappers.<AnnualRebateApproval>lambdaUpdate()
                    .set(AnnualRebateApproval::getOwnerId, bdmLog.getTargetUserId())
                    .set(AnnualRebateApproval::getOwnerName, bdmLog.getTargetUserName())
                    .set(AnnualRebateApproval::getDepartmentId, bdmLog.getTargetDepartmentId())
                    .set(AnnualRebateApproval::getCompanyId, bdmLog.getTargetCompanyId())
                    .set(AnnualRebateApproval::getUpdateBy, bdmLog.getOperatorId())
                    .set(AnnualRebateApproval::getUpdateName, bdmLog.getOperatorName())
                    .set(AnnualRebateApproval::getUpdateDate, bdmLog.getStartTime())
                    .eq(AnnualRebateApproval::getOwnerId, bdmLog.getSourceUserId()));
            bdmLog.setCount(ObjectUtils.defaultIfNull(bdmLog.getCount(), 0L).longValue() + dataList.size());
        }
        result.add(DataMoveResultDetail.builder().businessType(BusinessTypeEnum.ANNUAL_REBATE.getType()).ids(ids).build());
    }

    /**
     * 转移采购合同-业务数据
     * @param bdmLog
     * @param result
     */
    private void movePurchaseContract(BusinessDataMoveLog bdmLog, List<DataMoveResultDetail> result) {
        List<PurchaseContract> dataList = purchaseContractMapper.selectList(Wrappers.lambdaQuery(PurchaseContract.class)
                .select(PurchaseContract::getId).eq(PurchaseContract::getOwnerId, bdmLog.getSourceUserId()));
        List<Long> ids = null;
        if(CollectionUtils.isNotEmpty(dataList)) {
            ids = dataList.stream().map(PurchaseContract::getId).collect(Collectors.toList());
            purchaseContractMapper.updateByNoStrategy(Wrappers.<PurchaseContract>lambdaUpdate()
                    .set(PurchaseContract::getOwnerId, bdmLog.getTargetUserId())
                    .set(PurchaseContract::getOwnerName, bdmLog.getTargetUserName())
                    .set(PurchaseContract::getDepartmentId, bdmLog.getTargetDepartmentId())
                    .set(PurchaseContract::getCompanyId, bdmLog.getTargetCompanyId())
                    .set(PurchaseContract::getUpdateBy, bdmLog.getOperatorId())
                    .set(PurchaseContract::getUpdateName, bdmLog.getOperatorName())
                    .set(PurchaseContract::getUpdateDate, bdmLog.getStartTime())
                    .eq(PurchaseContract::getOwnerId, bdmLog.getSourceUserId()));
            bdmLog.setCount(ObjectUtils.defaultIfNull(bdmLog.getCount(), 0L).longValue() + dataList.size());
        }
        result.add(DataMoveResultDetail.builder().businessType(BusinessTypeEnum.PURCHASE_CONTRACT.getType()).ids(ids).build());
    }

    /**
     * 转移折扣返点审批单-业务数据
     * @param bdmLog
     * @param result
     */
    private void moveDiscountApproval(BusinessDataMoveLog bdmLog, List<DataMoveResultDetail> result) {
        List<DiscountApproval> dataList = discountApprovalMapper.selectList(Wrappers.lambdaQuery(DiscountApproval.class)
                .select(DiscountApproval::getId).eq(DiscountApproval::getOwnerId, bdmLog.getSourceUserId()));
        List<Long> ids = null;
        if(CollectionUtils.isNotEmpty(dataList)) {
            ids = dataList.stream().map(DiscountApproval::getId).collect(Collectors.toList());
            discountApprovalMapper.updateByNoStrategy(Wrappers.<DiscountApproval>lambdaUpdate()
                    .set(DiscountApproval::getOwnerId, bdmLog.getTargetUserId())
                    .set(DiscountApproval::getOwnerName, bdmLog.getTargetUserName())
                    .set(DiscountApproval::getDepartmentId, bdmLog.getTargetDepartmentId())
                    .set(DiscountApproval::getCompanyId, bdmLog.getTargetCompanyId())
                    .set(DiscountApproval::getUpdateBy, bdmLog.getOperatorId())
                    .set(DiscountApproval::getUpdateName, bdmLog.getOperatorName())
                    .set(DiscountApproval::getUpdateDate, bdmLog.getStartTime())
                    .eq(DiscountApproval::getOwnerId, bdmLog.getSourceUserId()));
            bdmLog.setCount(ObjectUtils.defaultIfNull(bdmLog.getCount(), 0L).longValue() + dataList.size());
        }
        result.add(DataMoveResultDetail.builder().businessType(BusinessTypeEnum.DISCOUNT_APPROVAL.getType()).ids(ids).build());
    }

    /**
     * 转移年框合同-业务数据
     * @param bdmLog
     * @param result
     */
    private void moveYearFrameContract(BusinessDataMoveLog bdmLog, List<DataMoveResultDetail> result) {
        List<YearFrameContract> dataList = yearFrameContractMapper.selectList(Wrappers.lambdaQuery(YearFrameContract.class)
                .select(YearFrameContract::getId).eq(YearFrameContract::getOwnerId, bdmLog.getSourceUserId()));
        List<Long> ids = null;
        if(CollectionUtils.isNotEmpty(dataList)) {
            ids = dataList.stream().map(YearFrameContract::getId).collect(Collectors.toList());
            yearFrameContractMapper.updateByNoStrategy(Wrappers.<YearFrameContract>lambdaUpdate()
                    .set(YearFrameContract::getOwnerId, bdmLog.getTargetUserId())
                    .set(YearFrameContract::getOwnerName, bdmLog.getTargetUserName())
                    .set(YearFrameContract::getDepartmentId, bdmLog.getTargetDepartmentId())
                    .set(YearFrameContract::getCompanyId, bdmLog.getTargetCompanyId())
                    .set(YearFrameContract::getUpdateBy, bdmLog.getOperatorId())
                    .set(YearFrameContract::getUpdateName, bdmLog.getOperatorName())
                    .set(YearFrameContract::getUpdateDate, bdmLog.getStartTime())
                    .eq(YearFrameContract::getOwnerId, bdmLog.getSourceUserId()));
            bdmLog.setCount(ObjectUtils.defaultIfNull(bdmLog.getCount(), 0L).longValue() + dataList.size());
        }
        result.add(DataMoveResultDetail.builder().businessType(BusinessTypeEnum.YEAR_FRAME_CONTRACT.getType()).ids(ids).build());
    }

    /**
     * 转移收入合同-业务数据
     * @param bdmLog
     * @param result
     */
    private void moveIncomeContract(BusinessDataMoveLog bdmLog, List<DataMoveResultDetail> result) {
        List<IncomeContract> dataList = incomeContractMapper.selectList(Wrappers.lambdaQuery(IncomeContract.class)
                .select(IncomeContract::getId).eq(IncomeContract::getOwnerId, bdmLog.getSourceUserId()));
        List<Long> ids = null;
        if(CollectionUtils.isNotEmpty(dataList)) {
            ids = dataList.stream().map(IncomeContract::getId).collect(Collectors.toList());
            incomeContractMapper.updateByNoStrategy(Wrappers.<IncomeContract>lambdaUpdate()
                    .set(IncomeContract::getOwnerId, bdmLog.getTargetUserId())
                    .set(IncomeContract::getOwnerName, bdmLog.getTargetUserName())
                    .set(IncomeContract::getDepartmentId, bdmLog.getTargetDepartmentId())
                    .set(IncomeContract::getCompanyId, bdmLog.getTargetCompanyId())
                    .set(IncomeContract::getUpdateBy, bdmLog.getOperatorId())
                    .set(IncomeContract::getUpdateName, bdmLog.getOperatorName())
                    .set(IncomeContract::getUpdateDate, bdmLog.getStartTime())
                    .eq(IncomeContract::getOwnerId, bdmLog.getSourceUserId()));
            bdmLog.setCount(ObjectUtils.defaultIfNull(bdmLog.getCount(), 0L).longValue() + dataList.size());
        }
        result.add(DataMoveResultDetail.builder().businessType(BusinessTypeEnum.INCOME_CONTRACT.getType()).ids(ids).build());
    }

    /**
     * 批量新增操作日志
     * @param bdmLog
     * @param detailList
     */
    private void insertOperateLogs(BusinessDataMoveLog bdmLog, List<DataMoveResultDetail> detailList) {
        try {
            if(bdmLog.getCount().longValue() <= 0) {
                return;
            }
            List<FieldChangeOperateLog> list = new ArrayList<>();
            for(DataMoveResultDetail detail : detailList) {
                if(CollectionUtils.isEmpty(detail.getIds())) {
                    continue;
                }
                BusinessTypeEnum businessTypeEnum = BusinessTypeEnum.toEnum(detail.getBusinessType());
                if(businessTypeEnum == null) {
                    continue;
                }
                detail.getIds().forEach(id -> {
                    LogBusinessTypeEnum logBusinessTypeEnum = null;
                    String operationField = null;
                    switch (businessTypeEnum) {
                        case CUSTOMER:
                            logBusinessTypeEnum = LogBusinessTypeEnum.CUSTOMER_PROFILE;
                            operationField = "团队成员";
                            break;
                        case STAR_AGENT:
                            logBusinessTypeEnum = LogBusinessTypeEnum.STAR_INFO;
                            operationField = "经纪人";
                            break;
                        case STAR_EXECUTOR:
                            logBusinessTypeEnum = LogBusinessTypeEnum.STAR_INFO;
                            operationField = "执行人";
                            break;
                        case YEAR_FRAME_CONTRACT:
                            logBusinessTypeEnum = LogBusinessTypeEnum.YEAR_FRAME_CONTRACT;
                            break;
                        case INCOME_CONTRACT:
                            logBusinessTypeEnum = LogBusinessTypeEnum.INCOME_CONTRACT;
                            break;
                        case EXCUTION_ORDER:
                            logBusinessTypeEnum = LogBusinessTypeEnum.EXECUTION_ORDER;
                            operationField = "执行人或统筹人";
                            break;
                        case STAR_REBATE_CONTRACT:
                            logBusinessTypeEnum = LogBusinessTypeEnum.STAR_REBATE_CONTRACT;
                        default:
                            break;
                    }
                    //记录数据所有人
                    if(logBusinessTypeEnum != null) {
                        FieldChangeOperateLog fieldChangeOperateLog = new FieldChangeOperateLog();
                        fieldChangeOperateLog.setBussinessId(id);
                        fieldChangeOperateLog.setBussinessType(logBusinessTypeEnum.getType());
                        fieldChangeOperateLog.setBeforeValue(bdmLog.getSourceUserName());
                        fieldChangeOperateLog.setAfterValue(bdmLog.getTargetUserName());
                        fieldChangeOperateLog.setOperationField(StringUtils.defaultString(operationField, "数据所有人"));
                        fieldChangeOperateLog.setOperationBy(bdmLog.getOperatorId());
                        fieldChangeOperateLog.setOperationName(bdmLog.getOperatorName());
                        fieldChangeOperateLog.setOperationType(OperationTypeEnum.UPDATE.getType());
                        fieldChangeOperateLog.setOperationTime(bdmLog.getStartTime());
                        list.add(fieldChangeOperateLog);
                    }
                });
            }
            if(CollectionUtils.isNotEmpty(list)) {
                OperateLogHandler.insertLog(list);
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
    }

    /**
     * 回滚财务
     * @param taskCode
     */
    private void rollbackFinance(String taskCode) {
        try {
            FinanceDataMoveDto rollbackRequest = new FinanceDataMoveDto();
            rollbackRequest.setTaskCode(taskCode);
            financeClient.dataMoveRollback(rollbackRequest);
        } catch (Exception exception) {
            log.error("财务-业务数据回滚异常！", exception);
        }
    }

    /**
     * 回滚BaseInfo
     * @param taskCode
     */
    private void rollbackBaseInfo(String taskCode) {
        try {
            baseInfoClient.userDataTransferReturn(taskCode);
        } catch (Exception exception) {
            log.error("baseInfo-业务数据回滚异常！", exception);
        }
    }

    /**
     * 是否需要回滚
     * @param e
     * @return
     */
    private  boolean rollbackIfNecessary(Exception e) {
        if(e instanceof RpcResultException) {
            return false;
        }
        return true;
    }

    /**
     * 数据转移结果明细
     */
    @Data
    @Builder
    public static class DataMoveResultDetail {
        /**
         * 业务类型
         */
        private Integer businessType;

        /**
         * 业务ID集合
         */
        private List<Long> ids;
    }
}
